/*  File Name	: Service.cpp
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2011-9-1
 *  Description:
 */

#include "Service.h"

#define BUFFER_BLOCK_SIZE	1024*512//接收消息缓存区大小

Service::Service(int p)
{
	memset(conn_addr_,'\0',sizeof(conn_addr_));
	this->port_= 0;
	this->last_recv_msg_ = 0;
	this->recv_msg_count_ = 0;
	this->timer_id_ = -1;
	this->unique_id_ = 0;//不用reset
	//this->monitor_ = NULL;
}

Service::~Service()
{

}

std::string Service::name(void)
{
	return "Service";
}

void Service::reset(void)
{
	memset(conn_addr_,'\0',sizeof(conn_addr_));
	this->port_= 0;
	this->last_recv_msg_ = 0;
	this->recv_msg_count_ = 0;
	this->timer_id_ = -1;
	//this->monitor_=NULL;
}

int Service::start_timer(TimeValue delay,TimeValue interval)
{
	this->timer_id_ = this->reactor()->schudle_timer(this,delay,interval);
	if(this->timer_id_ <=0)
	{
		return -1;
	}
	return this->timer_id_;
}

int Service::stop_timer(void)
{
	this->reactor()->cancel_timer(this->timer_id_);
	this->timer_id_ = -1;
	return 0;
}

long Service::timer_id(void)
{
	return this->timer_id_;
}

int Service::unique_id(void)
{
	return this->unique_id_;
}

void Service::set_unique_id(int id)
{
	this->unique_id_ = id;
}

const char *Service::peer_addr(void)
{
	return this->conn_addr_;
}

const int Service::peer_port(void)
{
	return this->port_;
}

int Service::open(void *)
{
	if (super::open(this->reactor()) != 0)
	{
		return -1;
	}

	this->msg_block_.init(BUFFER_BLOCK_SIZE*2);

	this->peer()->enable(O_NONBLOCK);
	int buf_length = 1024 * 1024;
	this->peer()->set_sockopt(SOL_SOCKET, SO_SNDBUF, &buf_length, sizeof(int));
	this->peer()->set_sockopt(SOL_SOCKET, SO_RCVBUF, &buf_length, sizeof(int));

	::sprintf(this->conn_addr_, "%s", this->peer()->get_host().c_str());
	this->port_ = this->peer()->get_port();

	this->last_recv_msg_ = TimeValue::now_time_in_sec();
	this->recv_msg_count_ = 0;

	return 0;
}

int Service::handle_input(int fd )
{
	return 0;
}

int Service::handle_output(int fd)
{
	return 0;
}

int Service::handle_timeout(void)
{
	return 0;
}

int Service::handle_close(int  fd,ReactorMask mask)
{
	return super::handle_close(fd,mask);
}

int Service::recv_msg(MessageBlock *mb,const int size,int flag)
{
	int len=this->peer()->recv(mb->wr_ptr(),size,flag);
	if(len>0)
	{
		mb->wr_len(len);
	}
	return len;
}

int Service::send_msg(MessageBlock *mb,int len,int flag)
{
	int total = 0;
	while(total<len)
	{
		int send=this->peer()->send(mb->rd_ptr()+total,len-total,flag);
		if(send>0)
		{
			total +=send;
			continue;
		}
		switch(errno)
		{
			case EWOULDBLOCK:
			{
				return 0;
			}
			case ETIME://timeout
			case EPIPE:
			default:
				break;
		}
	}
	return total;
}

/**
 * return
 *  0: write success
 * -1: no enough space error
 */
int Service::make_block(MessageBlock *mb,int len)
{
	if(this->msg_block_.make_block(mb,len)!=0)
	{
		//this->monitor()->msg_pool()->push(mb);
		LOG((ERROR_LOG,"Service::recv_msg-->make_block error"));
		return -1;
	}
	//this->monitor()->msg_pool()->push(mb);
	return 0;
}

/**
 * return
 *  2: success and have next  block
 *  1: success and have one block
 *  0: success but no message
 * -1: mb error
 * -2: space error,should close socket
 */

int Service::get_block(MessageBlock *mb)
{
	return this->msg_block_.get_block(mb);
}

//int Service::recycle(Service *s)
//{
//	return this->monitor_->svc_pool()->push(s);
//}

//Service::BaseMonitor *Service::monitor(BaseMonitor *monitor)
//{
//	if(NULL!=monitor)
//	{
//		this->monitor_ = monitor;
//	}
//	return this->monitor_;
//}

